<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="utf-8" />
        <title>Part.2.D.5-docstrings</title>
        <link rel="stylesheet" href="/theme/css/main.css" />

        <!--[if IE]>
            <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
</head>

<body id="index" class="home">
        <header id="banner" class="body">
                <h1><a href="/">PythonTutorials </a></h1>
                <nav><ul>
                    <li><a href="/category/cpp.html">cpp</a></li>
                    <li class="active"><a href="/category/python.html">python</a></li>
                </ul>
                </nav>
        </header><!-- /#banner -->
<section id="content" class="body">
  <article>
    <header>
      <h1 class="entry-title">
        <a href="/Part.2.D.5-docstrings.html" rel="bookmark"
           title="Permalink to Part.2.D.5-docstrings">Part.2.D.5-docstrings</a></h1>
    </header>

    <div class="entry-content">
<footer class="post-info">
        <span>Mon 06 April 2020</span>
<span>| tags: <a href="/tag/python.html">python</a><a href="/tag/progarmming.html">progarmming</a><a href="/tag/excel.html">Excel</a></span>
</footer><!-- /.post-info -->      <h1>函数的文档</h1>
<p>你在调用函数的时候，你像是函数这个产品的用户。</p>
<p>而你写一个函数，像是做一个产品，这个产品将来可能会被很多用户使用 —— 包括你自己。</p>
<p>产品，就应该有产品说明书，别人用得着，你自己也用得着 —— 很久之后的你，很可能把当初的各种来龙去脉忘得一干二净，所以也同样需要产品说明书，别看那产品曾经是你自己设计的。</p>
<p>Python 在这方面很用功，把函数的 “产品说明书” 当作语言内部的功能，这也是为什么 Python 有 <a href="http://www.sphinx-doc.org">Sphinx</a> 这种工具，而绝大多数其他语言没有的原因之一罢。</p>
<h2>Docstring</h2>
<p>在函数定义内部，我们可以加上 <strong>Docstring</strong>；将来函数的 “用户” 就可以通过 <code>help()</code> 这个内建函数，或者 <code>.__doc__</code> 这个 Method 去查看这个 Docstring，即，该函数的 “产品说明书”。</p>
<p>先看一个 Docstring 以及如何查看某个函数的 Docstring 的例子：</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return a boolean value based upon</span>
<span class="sd">    whether the argument n is a prime number.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">n</span><span class="o">**</span><span class="mf">0.5</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>

<span class="n">help</span><span class="p">(</span><span class="n">is_prime</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span><span class="p">)</span>
<span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span>
</pre></div>


<div class="highlight"><pre><span></span>Help on function is_prime in module __main__:

is_prime(n)
    Return a boolean value based upon
    whether the argument n is a prime number.

    Return a boolean value based upon
    whether the argument n is a prime number.

&#39;\n    Return a boolean value based upon\n    whether the argument n is a prime number.\n    &#39;
</pre></div>


<p>Docstring 可以是多行字符串，也可以是单行字符串：</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Return a boolean value based upon whether the argument n is a prime number.&quot;&quot;&quot;</span>

    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">n</span><span class="o">**</span><span class="mf">0.5</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>

<span class="n">help</span><span class="p">(</span><span class="n">is_prime</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span><span class="p">)</span>
<span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span>
</pre></div>


<div class="highlight"><pre><span></span>Help on function is_prime in module __main__:

is_prime(n)
    Return a boolean value based upon whether the argument n is a prime number.

Return a boolean value based upon whether the argument n is a prime number.

&#39;Return a boolean value based upon whether the argument n is a prime number.&#39;
</pre></div>


<p>Docstring 如若存在，必须在函数定义的内部语句块的开头，也必须与其它语句一样保持相应的缩进（Indention）。Docstring 放在其它地方不起作用：</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">False</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">n</span><span class="o">**</span><span class="mf">0.5</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">m</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="bp">True</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Return a boolean value based upon</span>
<span class="sd">    whether the argument n is a prime number.</span>
<span class="sd">    &quot;&quot;&quot;</span>

<span class="n">help</span><span class="p">(</span><span class="n">is_prime</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span><span class="p">)</span>
<span class="n">is_prime</span><span class="o">.</span><span class="vm">__doc__</span>
</pre></div>


<div class="highlight"><pre><span></span>Help on function is_prime in module __main__:

is_prime(n)

None
</pre></div>


<h2>书写 Docstring 的规范</h2>
<p>规范，虽然是人们最好遵守的，但其实通常是很多人并不遵守的东西。</p>
<p>既然学，就要<strong>像样</strong> —— 这真的很重要。所以，非常有必要认真阅读 Python <a href="https://www.python.org/dev/peps/pep-0257/">PEP 257</a> 关于 Docstring 的规范。</p>
<p>简要总结一下 PEP 257 中必须掌握的规范：</p>
<blockquote>
<ol>
<li>无论是单行还是多行的 Docstring，一概使用三个双引号扩起；</li>
<li>在 Docstring 内部，文字开始之前，以及文字结束之后，都不要有空行；</li>
<li>多行 Docstring，第一行是概要，随后空一行，再写其它部分；</li>
<li>完善的 Docstring，应该概括清楚以下内容：参数、返回值、可能触发的错误类型、可能的副作用，以及函数的使用限制等等；</li>
<li>每个参数的说明都使用单独的一行……</li>
</ol>
</blockquote>
<p>由于我们还没有开始研究 Class，所以，关于 Class 的 Docstring 应该遵守什么样的规范就暂时略过了。然而，这种规范你总是要反复去阅读参照的。关于 Docstring，有两个规范文件：</p>
<blockquote>
<ul>
<li><a href="https://www.python.org/dev/peps/pep-0257/">PEP 257: Docstring Convensions</a></li>
<li><a href="https://www.python.org/dev/peps/pep-0258/">PEP 258: Docutils Design Specification</a></li>
</ul>
</blockquote>
<p>需要<strong>格外注意</strong>的是：</p>
<blockquote>
<p>Docstring 是<strong>写给人看的</strong>，所以，在复杂代码的 Docstring 中，写 <strong>Why</strong> 要远比写 <em>What</em> 更重要 —— 你先记住这点，以后的体会自然会不断加深。</p>
</blockquote>
<h2>Sphinx 版本的 Docstring 规范</h2>
<p>Sphinx 可以从 <code>.py</code> 文件里提取所有 Docstring，而后生成完整的 Documentation。将来若是你写大型的项目，需要生成完善的文档的时候，你就会发现 Sphinx 是个 “救命” 的家伙，省时、省力、省心、省命……</p>
<p>在这里，没办法一下子讲清楚 Sphinx 的使用，尤其是它还用它自己的一种标记语言，reStructureText，文件尾缀使用 <code>.rst</code>……</p>
<p>但是，可以看一个例子：</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Vehicle</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&#39;&#39;&#39;</span>
<span class="sd">    The Vehicle object contains lots of vehicles</span>
<span class="sd">    :param arg: The arg is used for ...</span>
<span class="sd">    :type arg: str</span>
<span class="sd">    :param `*args`: The variable arguments are used for ...</span>
<span class="sd">    :param `**kwargs`: The keyword arguments are used for ...</span>
<span class="sd">    :ivar arg: This is where we store arg</span>
<span class="sd">    :vartype arg: str</span>
<span class="sd">    &#39;&#39;&#39;</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">arg</span> <span class="o">=</span> <span class="n">arg</span>

    <span class="k">def</span> <span class="nf">cars</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">distance</span><span class="p">,</span> <span class="n">destination</span><span class="p">):</span>
        <span class="sd">&#39;&#39;&#39;We can&#39;t travel a certain distance in vehicles without fuels, so here&#39;s the fuels</span>

<span class="sd">        :param distance: The amount of distance traveled</span>
<span class="sd">        :type amount: int</span>
<span class="sd">        :param bool destinationReached: Should the fuels be refilled to cover required distance?</span>
<span class="sd">        :raises: :class:`RuntimeError`: Out of fuel</span>

<span class="sd">        :returns: A Car mileage</span>
<span class="sd">        :rtype: Cars</span>
<span class="sd">        &#39;&#39;&#39;</span>
        <span class="k">pass</span>

<span class="n">help</span><span class="p">(</span><span class="n">Vehicle</span><span class="p">)</span>
</pre></div>


<div class="highlight"><pre><span></span><span class="nx">Help</span> <span class="nx">on</span> <span class="kr">class</span> <span class="nx">Vehicle</span> <span class="k">in</span> <span class="kr">module</span> <span class="nx">__main__</span><span class="o">:</span>

<span class="kr">class</span> <span class="nx">Vehicle</span><span class="p">(</span><span class="nx">builtins</span><span class="p">.</span><span class="nx">object</span><span class="p">)</span>
 <span class="o">|</span>  <span class="nx">Vehicle</span><span class="p">(</span><span class="nx">arg</span><span class="p">,</span> <span class="o">*</span><span class="nx">args</span><span class="p">,</span> <span class="o">**</span><span class="nx">kwargs</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">The</span> <span class="nx">Vehicle</span> <span class="nx">object</span> <span class="nx">contains</span> <span class="nx">lots</span> <span class="nx">of</span> <span class="nx">vehicles</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">param</span> <span class="nx">arg</span>: <span class="kt">The</span> <span class="nx">arg</span> <span class="nx">is</span> <span class="nx">used</span> <span class="k">for</span> <span class="p">...</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">type</span> <span class="nx">arg</span>: <span class="kt">str</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">param</span> <span class="sb">`*args`</span><span class="o">:</span> <span class="nx">The</span> <span class="nx">variable</span> <span class="nx">arguments</span> <span class="nx">are</span> <span class="nx">used</span> <span class="k">for</span> <span class="p">...</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">param</span> <span class="sb">`**kwargs`</span><span class="o">:</span> <span class="nx">The</span> <span class="nx">keyword</span> <span class="nx">arguments</span> <span class="nx">are</span> <span class="nx">used</span> <span class="k">for</span> <span class="p">...</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">ivar</span> <span class="nx">arg</span>: <span class="kt">This</span> <span class="nx">is</span> <span class="nx">where</span> <span class="nx">we</span> <span class="nx">store</span> <span class="nx">arg</span>
 <span class="o">|</span>  <span class="o">:</span><span class="nx">vartype</span> <span class="nx">arg</span>: <span class="kt">str</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">Methods</span> <span class="nx">defined</span> <span class="nx">here</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">arg</span><span class="p">,</span> <span class="o">*</span><span class="nx">args</span><span class="p">,</span> <span class="o">**</span><span class="nx">kwargs</span><span class="p">)</span>
 <span class="o">|</span>      <span class="nx">Initialize</span> <span class="nx">self</span><span class="p">.</span>  <span class="nx">See</span> <span class="nx">help</span><span class="p">(</span><span class="nx">type</span><span class="p">(</span><span class="nx">self</span><span class="p">))</span> <span class="k">for</span> <span class="nx">accurate</span> <span class="nx">signature</span><span class="p">.</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">cars</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">distance</span><span class="p">,</span> <span class="nx">destination</span><span class="p">)</span>
 <span class="o">|</span>      <span class="nx">We</span> <span class="nx">can</span><span class="s1">&#39;t travel a certain distance in vehicles without fuels, so here&#39;</span><span class="nx">s</span> <span class="nx">the</span> <span class="nx">fuels</span>
 <span class="o">|</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">param</span> <span class="nx">distance</span>: <span class="kt">The</span> <span class="nx">amount</span> <span class="nx">of</span> <span class="nx">distance</span> <span class="nx">traveled</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">type</span> <span class="nx">amount</span>: <span class="kt">int</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">param</span> <span class="kt">bool</span> <span class="nx">destinationReached</span>: <span class="kt">Should</span> <span class="nx">the</span> <span class="nx">fuels</span> <span class="nx">be</span> <span class="nx">refilled</span> <span class="nx">to</span> <span class="nx">cover</span> <span class="nx">required</span> <span class="nx">distance</span><span class="o">?</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">raises</span><span class="o">:</span> <span class="o">:</span><span class="kr">class</span><span class="o">:</span><span class="sb">`RuntimeError`</span><span class="o">:</span> <span class="nx">Out</span> <span class="nx">of</span> <span class="nx">fuel</span>
 <span class="o">|</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">returns</span>: <span class="kt">A</span> <span class="nx">Car</span> <span class="nx">mileage</span>
 <span class="o">|</span>      <span class="o">:</span><span class="nx">rtype</span>: <span class="kt">Cars</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="o">----------------------------------------------------------------------</span>
 <span class="o">|</span>  <span class="nx">Data</span> <span class="nx">descriptors</span> <span class="nx">defined</span> <span class="nx">here</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__dict__</span>
 <span class="o">|</span>      <span class="nx">dictionary</span> <span class="k">for</span> <span class="nx">instance</span> <span class="nx">variables</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__weakref__</span>
 <span class="o">|</span>      <span class="nx">list</span> <span class="nx">of</span> <span class="nx">weak</span> <span class="nx">references</span> <span class="nx">to</span> <span class="nx">the</span> <span class="nx">object</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>
</pre></div>


<p>通过插件，Sphinx 也能支持 Google Style Docstring 和 Numpy Style Docstring。</p>
<p>以下两个链接，放在这里，以便你将来查询：</p>
<blockquote>
<ul>
<li><a href="http://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html">sphinx.ext.napoleon – Support for NumPy and Google style docstrings</a></li>
<li><a href="https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html">sphinx.ext.autodoc – Include documentation from docstrings</a></li>
</ul>
</blockquote>
    </div><!-- /.entry-content -->

  </article>
</section>
        <section id="extras" class="body">
                <div class="blogroll">
                        <h2>blogroll</h2>
                        <ul>
                            <li><a href="http://getpelican.com/">Pelican</a></li>
                            <li><a href="http://python.org/">Python.org</a></li>
                            <li><a href="http://jinja.pocoo.org/">Jinja2</a></li>
                            <li><a href="#">You can modify those links in your config file</a></li>
                        </ul>
                </div><!-- /.blogroll -->
                <div class="social">
                        <h2>social</h2>
                        <ul>

                            <li><a href="#">You can add links in your config file</a></li>
                            <li><a href="#">Another social link</a></li>
                        </ul>
                </div><!-- /.social -->
        </section><!-- /#extras -->

        <footer id="contentinfo" class="body">
                <p>Powered by <a href="http://www.maxiaoan.com/">Maxiaoan</a></p>
        </footer><!-- /#contentinfo -->

</body>
</html>